#include "file_util.h"

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>

#include <sstream>
#include <fstream>
#include <iostream>

/**   文件类
 * @brief   读取文件内容
 * @param[in]   const char* file_path   文件路径
 * @param[out]  long&       length      文件长度
 * @param[out]  char**      memory      指向文件内容的二级指针
 * @return      int         状态码
 */
int FileUtil::read_file(const char* file_path, long& length,
                              char** memory) {
    std::fstream fs;
    fs.open(file_path, std::ios::in | std::ios::binary);

    if (!fs) {
        return -1;
    }

    fs.seekg(0, std::ios::end);
    length = fs.tellg();
    fs.seekg(0, std::ios::beg);
    *memory = new char[length];
    fs.read(*memory, length);
    fs.close();

    return 0;
}

std::string FileUtil::read_fileContent(const std::string& filePath) 
{
    std::ifstream fileStream(filePath);  // 打开文件
    if (!fileStream.is_open()) {
        std::cerr << "Failed to open file: " << filePath << std::endl;
        return "";  // 返回空字符串，表示读取失败
    }

    // 使用 stringstream 读取文件内容
    std::stringstream buffer;
    buffer << fileStream.rdbuf();  // 将文件内容读入到 stringstream

    fileStream.close();  // 关闭文件流
    return buffer.str();  // 返回文件内容字符串
}

int FileUtil::file_type(const char* file_path) {
    if (file_path == nullptr) {
        std::cout << "file is not exist" << std::endl;
        return FILE_TYPE_NOT_EXIST;
    }
    std::string path(file_path);
    if (path.find("http://") == 0 || path.find("https://") == 0 ||
        path.find("rtsp://") == 0 || path.find("rtmp://") == 0 ||
        path.find("udp://") == 0 || path.find("rtp://") == 0) {
        return FILE_TYPE_URL;
    }
    if (access(file_path, F_OK) != 0) {
        std::cout << " [" << std::string(file_path) << "] file is not exist"
                  << std::endl;
        return FILE_TYPE_NOT_EXIST;
    }
    struct stat path_stat;
    stat(file_path, &path_stat);
    if (S_ISDIR(path_stat.st_mode)) {
        return FILE_TYPE_DIR;
    }
    if (S_ISCHR(path_stat.st_mode) || S_ISBLK(path_stat.st_mode)) {
        return FILE_TYPE_DEVICE;
    }
    if (!S_ISREG(path_stat.st_mode)) {
        return FILE_TYPE_UNKNOW;
    }
    std::string::size_type idx = path.rfind('.');
    if (idx == std::string::npos) {
        return FILE_TYPE_UNKNOW;
    }
    std::string suffix = path.substr(idx + 1);
    if (strcasecmp(suffix.c_str(), "jpg") == 0 ||
        strcasecmp(suffix.c_str(), "jpeg") == 0 ||
        strcasecmp(suffix.c_str(), "png") == 0 ||
        strcasecmp(suffix.c_str(), "bmp") == 0) {
        return FILE_TYPE_IMAGE;
    }

    if (strcasecmp(suffix.c_str(), "mp4") == 0 ||
        strcasecmp(suffix.c_str(), "avi") == 0 ||
        strcasecmp(suffix.c_str(), "mkv") == 0 ||
        strcasecmp(suffix.c_str(), "rmvb") == 0 ||
        strcasecmp(suffix.c_str(), "264") == 0 ||
        strcasecmp(suffix.c_str(), "265") == 0 ||
        strcasecmp(suffix.c_str(), "h264") == 0 ||
        strcasecmp(suffix.c_str(), "h265") == 0) {
        return FILE_TYPE_VIDEO;
    }
    return FILE_TYPE_UNKNOW;
}

bool FileUtil::create_dir(const std::string &path_) {
    std::string path = path_;
    size_t lastSlashPos = path.find_last_of('/');
    if (lastSlashPos != std::string::npos) {
        std::string lastPart = path.substr(lastSlashPos + 1);
        if (lastPart.find('.') != std::string::npos) {
            // 如果路径最后一部分包含'.'，则认为是文件而非目录，去除之
            path = path.substr(0, lastSlashPos);
        }
    }
    if(access(path.c_str(), F_OK) == 0) {
        return true;
    }
    size_t pos = 0;
    do {
        pos = path.find_first_of('/', pos + 1);
        std::string subDir = path.substr(0, pos);
        if (!subDir.empty()) {
            int result = mkdir(subDir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); // 777 权限
            if (result != 0 && errno != EEXIST) {
                std::cerr << "无法创建目录 " << subDir << ": " << strerror(errno) << std::endl;
                return false;
            }
        }
    } while (pos != std::string::npos);

    return true;
}

bool FileUtil::delete_directory(const std::string &dir_path) 
{
    if(dir_path.empty())return false;
    DIR *dir = opendir(dir_path.c_str());
    if (dir == nullptr) {
        perror("Failed to open directory");
        return false;
    }

    struct dirent *entry;
    bool success = true;

    while ((entry = readdir(dir)) != nullptr) {
        std::string entry_name = entry->d_name;
        if (entry_name == "." || entry_name == "..") {
            continue;  // 忽略当前目录和上级目录
        }

        std::string entry_path = dir_path + "/" + entry_name;
        struct stat entry_stat;
        if (stat(entry_path.c_str(), &entry_stat) == -1) {
            perror("Failed to get file status");
            success = false;
            break;
        }

        if (S_ISDIR(entry_stat.st_mode)) {
            // 如果是目录，递归删除
            if (!delete_directory(entry_path)) {
                success = false;
                break;
            }
        } else {
            // 如果是文件，直接删除
            if (unlink(entry_path.c_str()) == -1) {
                perror("Failed to remove a file");
                success = false;
                break;
            }
        }
    }

    closedir(dir);

    // 删除当前目录
    if (success && rmdir(dir_path.c_str()) == -1) {
        perror("Failed to remove directory");
        return false;
    }

    return success;
}